package cn.zhentao.service;

import cn.zhentao.entity.GameSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 游戏会话管理服务
 */
@Slf4j
@Service
public class GameSessionService {
    
    /**
     * 游戏会话缓存 - 实际项目中可以使用Redis
     */
    private final Map<String, GameSession> sessionCache = new ConcurrentHashMap<>();
    
    /**
     * 会话超时时间（分钟）
     */
    private static final int SESSION_TIMEOUT_MINUTES = 30;
    
    /**
     * 创建新的游戏会话
     */
    public GameSession createGameSession(Long userId, String gameType) {
        String sessionId = generateSessionId(userId, gameType);

        // 检查是否已存在会话，如果存在则删除旧的
        if (sessionCache.containsKey(sessionId)) {
            log.info("删除已存在的游戏会话: sessionId={}", sessionId);
            sessionCache.remove(sessionId);
        }

        GameSession session = new GameSession();
        session.setSessionId(sessionId);
        session.setUserId(userId);
        session.setGameType(gameType);
        session.setGameState(GameSession.GameState.WAITING);

        // 根据游戏类型设置特定配置
        configureGameByType(session, gameType);

        sessionCache.put(sessionId, session);
        log.info("创建游戏会话: userId={}, gameType={}, sessionId={}", userId, gameType, sessionId);

        return session;
    }
    
    /**
     * 获取游戏会话
     */
    public GameSession getGameSession(String sessionId) {
        GameSession session = sessionCache.get(sessionId);
        if (session != null && isSessionValid(session)) {
            return session;
        }
        return null;
    }
    
    /**
     * 获取或创建游戏会话
     */
    public GameSession getOrCreateGameSession(Long userId, String gameType) {
        String sessionId = generateSessionId(userId, gameType);
        GameSession session = sessionCache.get(sessionId);

        // 检查会话是否有效
        if (session != null && isSessionValid(session)) {
            log.debug("复用现有游戏会话: sessionId={}", sessionId);
            return session;
        }

        // 创建新会话
        log.info("创建新游戏会话: userId={}, gameType={}", userId, gameType);
        session = createGameSession(userId, gameType);

        return session;
    }
    
    /**
     * 更新游戏会话
     */
    public void updateGameSession(GameSession session) {
        session.setUpdateTime(LocalDateTime.now());
        sessionCache.put(session.getSessionId(), session);
        log.debug("更新游戏会话: sessionId={}, state={}, score={}", 
                 session.getSessionId(), session.getGameState(), session.getScore());
    }
    
    /**
     * 开始游戏
     */
    public void startGame(String sessionId) {
        GameSession session = getGameSession(sessionId);
        if (session != null) {
            session.setGameState(GameSession.GameState.PLAYING);
            updateGameSession(session);
        }
    }
    
    /**
     * 暂停游戏
     */
    public void pauseGame(String sessionId) {
        GameSession session = getGameSession(sessionId);
        if (session != null) {
            session.setGameState(GameSession.GameState.PAUSED);
            updateGameSession(session);
        }
    }
    
    /**
     * 结束游戏
     */
    public void finishGame(String sessionId) {
        GameSession session = getGameSession(sessionId);
        if (session != null) {
            session.setGameState(GameSession.GameState.FINISHED);
            updateGameSession(session);
            log.info("游戏结束: sessionId={}, 最终得分={}, 准确率={}%", 
                    sessionId, session.getScore(), session.getGameStats().getAccuracyRate());
        }
    }
    
    /**
     * 记录游戏答题
     */
    public void recordAnswer(String sessionId, String question, String userAnswer, 
                           String correctAnswer, boolean isCorrect, Long responseTimeMs) {
        GameSession session = getGameSession(sessionId);
        if (session != null) {
            session.addGameRecord(question, userAnswer, correctAnswer, isCorrect, responseTimeMs);
            updateGameSession(session);
        }
    }
    
    /**
     * 使用提示
     */
    public boolean useHint(String sessionId) {
        GameSession session = getGameSession(sessionId);
        if (session != null) {
            boolean used = session.useHint();
            if (used) {
                updateGameSession(session);
            }
            return used;
        }
        return false;
    }
    
    /**
     * 删除游戏会话
     */
    public void removeGameSession(String sessionId) {
        sessionCache.remove(sessionId);
        log.info("删除游戏会话: sessionId={}", sessionId);
    }
    
    /**
     * 清理过期会话
     */
    public void cleanExpiredSessions() {
        LocalDateTime expireTime = LocalDateTime.now().minusMinutes(SESSION_TIMEOUT_MINUTES);
        sessionCache.entrySet().removeIf(entry -> {
            GameSession session = entry.getValue();
            boolean expired = session.getUpdateTime().isBefore(expireTime);
            if (expired) {
                log.info("清理过期会话: sessionId={}", entry.getKey());
            }
            return expired;
        });
    }
    
    /**
     * 生成会话ID - 使用固定格式确保同一用户同一游戏类型的会话ID一致
     */
    private String generateSessionId(Long userId, String gameType) {
        return String.format("game_%s_%s", gameType, userId);
    }
    
    /**
     * 检查会话是否有效
     */
    private boolean isSessionValid(GameSession session) {
        LocalDateTime expireTime = LocalDateTime.now().minusMinutes(SESSION_TIMEOUT_MINUTES);
        return session.getUpdateTime().isAfter(expireTime);
    }
    
    /**
     * 根据游戏类型配置游戏
     */
    private void configureGameByType(GameSession session, String gameType) {
        GameSession.GameConfig config = session.getGameConfig();
        
        switch (gameType) {
            case "riddle":
                config.setMaxQuestions(5);
                config.setTimeLimit(120);
                config.setDifficulty("normal");
                config.setPointsPerCorrect(20);
                break;
                
            case "idiom":
                config.setMaxQuestions(8);
                config.setTimeLimit(90);
                config.setDifficulty("normal");
                config.setPointsPerCorrect(15);
                config.setEnableHints(false); // 成语接龙不提供提示
                break;
                
            case "quiz":
                config.setMaxQuestions(10);
                config.setTimeLimit(60);
                config.setDifficulty("normal");
                config.setPointsPerCorrect(10);
                config.setHintsRemaining(2);
                break;
                
            case "story":
                config.setMaxQuestions(6);
                config.setTimeLimit(180);
                config.setDifficulty("easy");
                config.setPointsPerCorrect(25);
                config.setEnableHints(false); // 故事接龙不需要提示
                break;
                
            default:
                // 使用默认配置
                break;
        }
    }
    
    /**
     * 获取用户游戏统计
     */
    public GameSession.GameStats getUserGameStats(Long userId, String gameType) {
        String sessionId = generateSessionId(userId, gameType);
        GameSession session = getGameSession(sessionId);
        
        if (session != null) {
            return session.getGameStats();
        }
        
        // 返回空统计
        GameSession.GameStats stats = new GameSession.GameStats();
        stats.setTotalQuestions(0);
        stats.setCorrectAnswers(0);
        stats.setAccuracyRate(0.0);
        stats.setAverageResponseTime(0.0);
        return stats;
    }
    
    /**
     * 调整游戏难度
     */
    public void adjustDifficulty(String sessionId, String difficulty) {
        GameSession session = getGameSession(sessionId);
        if (session != null) {
            session.getGameConfig().setDifficulty(difficulty);
            
            // 根据难度调整分数倍数
            switch (difficulty) {
                case "easy":
                    session.getGameConfig().setBonusMultiplier(1);
                    break;
                case "normal":
                    session.getGameConfig().setBonusMultiplier(2);
                    break;
                case "hard":
                    session.getGameConfig().setBonusMultiplier(3);
                    break;
            }
            
            updateGameSession(session);
        }
    }
}
